﻿using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
using System.Collections.ObjectModel;
using System.ComponentModel.DataAnnotations;
using System.IO;
using VideoTools.Config;

namespace VideoTools
{
    public sealed class AppConfig : NotifyPropertyBase, IConfigFile, IDisposable
    {
        private static volatile AppConfig _instance;
        private static readonly object SyncRoot = new object();

        public static AppConfig Instance
        {
            get
            {
                if (_instance == null)
                {
                    lock (SyncRoot)
                    {
                        if (_instance == null)
                        {
                            _instance = new AppConfig();
                        }
                    }
                }

                return _instance;
            }
        }
        private volatile bool _isDisposed = false;
        private readonly object _syncObject = new object();
        private ConfigFileSaveWorker _configFileSaveWorker;
        private static string configBaseName = "config.json";
        private readonly string _configFilePath = System.IO.Path.Combine(AppConstants.AppDataFolderPath, configBaseName);
        private AppConfig()
        {
            JsonConvert.DefaultSettings = () =>
                new JsonSerializerSettings
                {
                    Formatting = Formatting.Indented,
                    NullValueHandling = NullValueHandling.Ignore,
                    Converters = new JsonConverter[]
                    {
                        new StringEnumConverter { AllowIntegerValues = false },
                    },
                };
            try
            {
                Load(_configFilePath);
            }
            catch { }

            _configFileSaveWorker = new ConfigFileSaveWorker(this, _configFilePath);

            this.PropertyChanged += (s, e) =>
            {
                _configFileSaveWorker?.SetModifiedConfigData();
            };
        }
        public void Save(string filePath)
        {
            lock (_syncObject)
            {
                var sortedProperties = JObject.FromObject(this).Properties().OrderBy(J => J.Name);
                var jobj = new JObject(sortedProperties.Cast<object>().ToArray());
                File.WriteAllText(filePath, jobj.ToString());
            }
        }
        public void Save()
        {
            Save(_configFilePath);
        }

        public void Load(string filePath)
        {
            lock (_syncObject)
            {
                string dir = Path.GetDirectoryName(filePath);
                if (!Directory.Exists(dir))
                {
                    Directory.CreateDirectory(dir);
                }
                if (!File.Exists(filePath))
                {
                    File.Copy("./" + configBaseName, filePath, true);
                }
                var json = File.ReadAllText(filePath);
                JsonConvert.PopulateObject(json, this);
            }
        }
        public void Dispose()
        {
            try
            {
                lock (_syncObject)
                {
                    if (_isDisposed)
                        return;

                    _configFileSaveWorker?.Dispose();
                    _configFileSaveWorker = null;

                    _isDisposed = true;
                }
            }
            catch { }
        }
        private string _DefaultPage;

        public string DefaultPage
        {
            get => _DefaultPage;
            set => SetProperty(ref _DefaultPage, value);
        }
        private string _VideoPlayerPath = @"C:\Program Files\DAUM\PotPlayer\PotPlayerMini64.exe";

        public string VideoPlayerPath
        {
            get => _VideoPlayerPath;
            set => SetProperty(ref _VideoPlayerPath, value);
        }
        private string _DefaultTitle;

        public string DefaultTitle
        {
            get => _DefaultTitle;
            set => SetProperty(ref _DefaultTitle, value);
        }
        private int _LastRandomTranslateCount = 10;
        public int LastRandomTranslateCount
        {
            get => _LastRandomTranslateCount;
            set => SetProperty(ref _LastRandomTranslateCount, value);
        }
        private string _LastRandomTranslate;
        public string LastRandomTranslate
        {
            get => _LastRandomTranslate;
            set => SetProperty(ref _LastRandomTranslate, value);
        }

        private string _JianYingOutPath;
        public string JianYingOutPath
        {
            get => _JianYingOutPath;
            set => SetProperty(ref _JianYingOutPath, value);
        }
        private string _JianYingDraftPath;
        public string JianYingDraftPath
        {
            get => _JianYingDraftPath;
            set => SetProperty(ref _JianYingDraftPath, value);
        }



        private string _EsFingerprint;
        public string EsFingerprint
        {
            get => _EsFingerprint;
            set => SetProperty(ref _EsFingerprint, value);
        }

        private string _EsUserName;
        public string EsUserName
        {
            get => _EsUserName;
            set => SetProperty(ref _EsUserName, value);
        }

        private string _EsPassword;
        public string EsPassword
        {
            get => _EsPassword;
            set => SetProperty(ref _EsPassword, value);
        }

        private string _EsAddress;
        public string EsAddress
        {
            get => _EsAddress;
            set => SetProperty(ref _EsAddress, value);
        }
        private string _BackgroundColor = "Red";

        public string BackgroundColor
        {
            get => _BackgroundColor;
            set => SetProperty(ref _BackgroundColor, value);
        }

        private string _AccentName;
        public string AccentName
        {
            get => _AccentName;
            set => SetProperty(ref _AccentName, value);
        }

        private ObservableCollection<string> _SearchNameHistorys = new ObservableCollection<string>();
        public ObservableCollection<string> SearchNameHistorys
        {
            get => _SearchNameHistorys;
            set => SetProperty(ref _SearchNameHistorys, value);
        }

        private ObservableCollection<string> _NameHistorys = new ObservableCollection<string>();
        public ObservableCollection<string> NameHistorys
        {
            get => _NameHistorys;
            set => SetProperty(ref _NameHistorys, value);
        }

        private ObservableCollection<string> _VideoHistorys = new ObservableCollection<string>();
        public ObservableCollection<string> VideoHistorys
        {
            get => _VideoHistorys;
            set => SetProperty(ref _VideoHistorys, value);
        }

        private int _MaxThreadCount = 5;
        /// <summary>
        /// 线程数量
        /// </summary>
        [Range(1, 20)]
        public int MaxThreadCount
        {
            get => _MaxThreadCount;
            set { SetProperty(ref _MaxThreadCount, value); }
        }

        /// <summary>
        /// 同时下载的任务数量
        /// </summary>
        [Range(1, 30)]
        private int _MaxConcurrentDownloadCount = 5;
        public int MaxConcurrentDownloadCount
        {
            get => _MaxConcurrentDownloadCount;
            set { SetProperty(ref _MaxConcurrentDownloadCount, value);
                OnPropertyChanged(nameof(MaxConcurrentDownloadCount));
            }
        }

        [Range(1, 20)]
        private int _RetryCount = 5;
        public int RetryCount
        {
            get => _RetryCount;
            set { SetProperty(ref _RetryCount, value); }
        }

        private string _SavePath = Path.Combine(System.Environment.CurrentDirectory, "download");
        public string SavePath
        {
            get => _SavePath;
            set { SetProperty(ref _SavePath, value); }
        }
        private int _SelectedMaxSize = 0;
        public int SelectedMaxSize
        {
            get => _SelectedMaxSize;
            set { SetProperty(ref _SelectedMaxSize, value); }
        }
        private bool _ForcedMerger = true;
        public bool ForcedMerger
        {
            get => _ForcedMerger;
            set { SetProperty(ref _ForcedMerger, value); }
        }
        private bool _IsCleanUp = true;
        public bool IsCleanUp
        {
            get => _IsCleanUp;
            set { SetProperty(ref _IsCleanUp, value); }
        }

        private string _Headers ;
        public string Headers
        {
            get => _Headers;
            set { SetProperty(ref _Headers, value); }
        }

        [Range(1, 60)]
        private int _Timeouts  = 10;
        public int Timeouts
        {
            get => _Timeouts;
            set { SetProperty(ref _Timeouts, value); }
        }
        [Range(0, 30)]
        private int _Fps = 0;
        public int Fps
        {
            get => _Fps;
            set { SetProperty(ref _Fps, value); }
        }
    }
}
